#!/usr/bin/python
# -*-coding:UTF-8 -*-

# ========================
# @Time  : 2021/2/25
# @Author: Sunny
# ========================

"""
1、描述并发和并行的概念
并发：指CPU核数小于任务数，通过操作系统的任务调度算法，实现多个任务“一起执行”（实际上总有一些任务不在执行，为交替执行的状态，
      因为切换的速度相当快，看上去一起执行而已）
并行：指CPU核数大于任务是，真正的一对一提供支持，真正在同一时间上进行处理


2、描述python中线程的缺陷，以及适用场景
缺陷：由于GIL锁的存在，python中的多线程在同一时间没办法同时实行(即无法实现并行)

使用场景：涉及到网络、磁盘IO的任务都是IO密集型任务（指读写操作或者输入输出操作），这类任务的特点是CPU消耗很少，任务的大部分时间都在等待IO操作完成
        (因为IO的速度远远低于CPU和内存的速度)

3、一个列表中有100个url地址（假设请求每个地址需要0.5秒），请设计程序一个程序，获取列表中的url地址，使用4个线程去发送这100个请求，计算出总耗时！

"""
import requests
from threading import Thread
import time


# 定义装饰器
def decorator(func):
    def wrapper(*args):
        # 获取程序执行前的时间
        start = time.time()
        # 执行功能程序
        func(*args)
        # 获取程序执行后的时间
        end = time.time()
        print(f'程序的执行时间为:{end - start}')
        return end - start

    return wrapper


# 定义线程类
class MyThread(Thread):
    def __init__(self, url_list):
        super().__init__()
        self.url_list = url_list

    # def run(self):
    #     while self.url_list:
    #         url = self.url_list.pop()
    #         # requests.get(url=url)
    #         time.sleep(0.5)
    #         print(f'{self}发送请求{url}')

    def run(self):
        while True:
            try:
                url = next(urls_g)
            except StopIteration:
                break
            else:
                # requests.get(url=url)
                print(f'{self}发送请求{url}')
                time.sleep(0.5)


@decorator  # main = docaretor(main)
def main(url_list):
    """创建线程"""
    t_list = []
    for a in range(4):
        t = MyThread(url_list)
        t.start()
        t_list.append(t)

    for t in t_list:
        # 子线程等待
        t.join()


# url_list = [f'https://www.baidu.com-{i}' for i in range(100)]  #列表
urls_g = (f'https://www.baidu.com-{i}'for i in range(100))  #生成器 更节约内存
main(urls_g)

#线程开的太多，可能主程序就会崩掉，装饰器就统计不出来时间了
